"""JD Chain区块链适配器

实现JD Chain区块链平台的适配器，通过Java SDK桥接提供与JD Chain网络交互的功能
注意：JD Chain官方不支持Python SDK，此适配器通过Java进程桥接实现
"""

import json
import asyncio
import aiohttp
from typing import Dict, List, Any, Optional
from datetime import datetime
import os
from utils.logger import get_logger
from utils.exceptions import ChainException, TransactionException, ContractException
from middleware.unified_abstraction import (
    AccountInfo, BlockInfo, TransactionInfo, ContractInfo, ChainInfo
)
from .base_adapter import BaseBlockchainAdapter

logger = get_logger(__name__)

class JDChainAdapter(BaseBlockchainAdapter):
    """JD Chain区块链适配器
    
    由于JD Chain官方不支持Python SDK，此适配器通过Java进程桥接实现
    需要预先配置Java环境和JD Chain Java SDK
    """
    
    def __init__(self, config: Dict[str, Any]):
        """初始化JD Chain适配器"""
        super().__init__(config)
        
        # 网关配置
        self.gateway_host = config.get('gateway_host', 'localhost')
        self.gateway_port = config.get('gateway_port', 8080)
        self.gateway_secure = config.get('gateway_secure', False)  # 是否使用HTTPS
        
        # JD Chain特定配置
        self.ledger_hash = config.get('ledger_hash', '')
        
        # 认证配置
        self.user_name = config.get('user_name', '')
        self.user_pub_key = config.get('user_pub_key', '')
        self.user_priv_key = config.get('user_priv_key', '')
        self.admin_password = config.get('admin_password', '')
        self.contract_address = config.get('contract_address', '')
        self.data_account_address = config.get('data_account_address', '')
        
        # 连接状态
        self._connected = False
        self.gateway_url = None
        # 使用JDChain Spring Boot REST API的基础URL
        self.base_url = f"http://{self.gateway_host}:{self.gateway_port}"
        self.api_base_url = "http://192.168.1.57:8582/api/contract"
        
        logger.info(f"Initialized JD Chain adapter for ledger {self.ledger_hash}")
    
    async def _establish_connection(self):
        """建立与JD Chain节点的连接"""
        try:
            # 构建网关URL
            protocol = 'https' if self.gateway_secure else 'http'
            self.gateway_url = f"{protocol}://{self.gateway_host}:{self.gateway_port}"
            
            # 测试连接
            await self._test_connection()
            
            self._connected = True
            
        except Exception as e:
            raise ChainException(f"Failed to establish JD Chain connection: {str(e)}", self.chain_id)
    
    async def _close_connection(self):
        """关闭连接"""
        self._connected = False
    
    async def _check_connection_health(self) -> bool:
        """检查连接健康状态"""
        try:
            if not self._connected:
                return False
            
            # 通过HTTP API检查连接
            result = await self._http_request('GET', '/ledgers')
            return result is not None and result.get('success', False)
            
        except Exception:
            return False
    
    async def _test_connection(self):
        """测试连接"""
        try:
            # 测试JDChain Spring Boot REST API健康检查
            import aiohttp
            url = f"{self.api_base_url}/"
            
            async with aiohttp.ClientSession() as session:
                async with session.get(url) as response:
                    response.raise_for_status()
                    data = await response.json()
                    
                    # 检查API响应
                    if data.get('success') and data.get('data') == '服务正常运行':
                        logger.info(f"Successfully connected to JDChain Spring Boot REST API")
                        return True
                    else:
                        logger.warning(f"JDChain Spring Boot REST API health check failed: {data}")
                        return False
                         
        except Exception as e:
            logger.error(f"Connection test failed: {str(e)}")
            return False
    
    async def _http_request(self, method: str, path: str, data: Dict[str, Any] = None) -> Dict[str, Any]:
        """发送HTTP请求到JD Chain网关"""
        import aiohttp
        import base64
        
        url = f"{self.gateway_url}{path}"
        
        # 准备请求头
        headers = {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }
        
        # JDChain的REST API通常不需要HTTP基本认证
        # 认证通过交易签名在业务层处理
        
        try:
            async with aiohttp.ClientSession() as session:
                if method.upper() == 'GET':
                    async with session.get(url, headers=headers) as response:
                        response.raise_for_status()
                        return await response.json()
                elif method.upper() == 'POST':
                    async with session.post(url, json=data, headers=headers) as response:
                        response.raise_for_status()
                        return await response.json()
                else:
                    raise ChainException(f"Unsupported HTTP method: {method}", self.chain_id)
        except Exception as e:
            raise ChainException(f"HTTP request failed: {str(e)}, url={url}", self.chain_id)
    
    async def _get_chain_info_impl(self) -> ChainInfo:
        """获取JD Chain链信息"""
        try:
            # 首先获取账本列表
            ledgers_result = await self._http_request('GET', '/ledgers')
            if not ledgers_result.get('success', False):
                raise ChainException(f"Failed to get ledger list: {ledgers_result.get('error', {}).get('errorMessage', 'Unknown error')}", self.chain_id)
            
            ledgers = ledgers_result.get('data', [])
            if not ledgers:
                raise ChainException("No ledgers found", self.chain_id)
            
            # 使用第一个账本或指定的账本
            target_ledger = self.ledger_hash if self.ledger_hash else ledgers[0]
            
            # 获取账本详细信息
            ledger_result = await self._http_request('GET', f'/ledgers/{target_ledger}')
            if not ledger_result.get('success', False):
                raise ChainException(f"Failed to get ledger info: {ledger_result.get('error', {}).get('errorMessage', 'Unknown error')}", self.chain_id)
            
            ledger_info = ledger_result.get('data', {})
            
            return ChainInfo(
                chain_id=str(self.chain_id),
                chain_name='jdchain',
                network_id=ledger_info.get('hash', target_ledger),
                latest_block=ledger_info.get('latestBlockHeight', 0),
                consensus='BFTSMaRt',  # JD Chain默认共识算法
                version='1.0.0'  # 默认版本
            )
            
        except Exception as e:
            raise ChainException(f"Failed to get chain info: {str(e)}", self.chain_id)
    
    async def create_account(self, **kwargs) -> AccountInfo:
        """创建JD Chain账户"""
        try:
            # JD Chain账户创建需要通过交易执行
            account_name = kwargs.get('account_name', f"account_{self._generate_request_id()}")
            pub_key = kwargs.get('pub_key', '')
            
            result = await self._call_java_method('createAccount', {
                'accountName': account_name,
                'pubKey': pub_key
            })
            
            return AccountInfo(
                address=result.get('address', ''),
                balance=0.0,
                nonce=0,
                code='',
                storage_root='',
                code_hash=''
            )
            
        except Exception as e:
            raise ChainException(f"Failed to create account: {str(e)}", self.chain_id, 'create_account')
    
    async def get_account_info(self, address: str) -> AccountInfo:
        """获取账户信息"""
        await self._ensure_connected()
        
        try:
            account_info = await self._call_java_method('getAccount', {'address': address})
            
            return AccountInfo(
                address=address,
                balance=0.0,  # JD Chain联盟链通常不涉及代币余额
                nonce=account_info.get('nonce', 0),
                code='',
                storage_root='',
                code_hash=''
            )
            
        except Exception as e:
            raise ChainException(f"Failed to get account info: {str(e)}", self.chain_id, 'get_account_info')
    
    async def get_balance(self, address: str, token_address: str = None) -> float:
        """获取账户余额"""
        await self._ensure_connected()
        
        try:
            # JD Chain联盟链通常不涉及代币余额概念
            return 0.0
                
        except Exception as e:
            raise ChainException(f"Failed to get balance: {str(e)}", self.chain_id, 'get_balance')
    
    async def send_transaction(self, transaction: Dict[str, Any]) -> str:
        """发送交易"""
        await self._ensure_connected()
        
        try:
            # 构建JD Chain交易
            tx_data = {
                'txType': transaction.get('tx_type', 'CONTRACT'),
                'contractAddress': transaction.get('contract_address', ''),
                'operation': transaction.get('operation', ''),
                'args': transaction.get('args', {})
            }
            
            # 发送交易
            result = await self._call_java_method('sendTransaction', tx_data)
            
            if not result or not result.get('txHash'):
                raise TransactionException("Failed to send transaction", None, self.chain_id)
            
            tx_hash = result.get('txHash')
            logger.info(f"Transaction sent successfully: {tx_hash}")
            return tx_hash
            
        except Exception as e:
            raise TransactionException(f"Failed to send transaction: {str(e)}", None, self.chain_id)
    
    async def get_transaction(self, tx_hash: str) -> TransactionInfo:
        """获取交易信息"""
        await self._ensure_connected()
        
        try:
            tx_data = await self._call_java_method('getTransaction', {'txHash': tx_hash})
            
            if not tx_data:
                raise TransactionException(f"Transaction not found: {tx_hash}", tx_hash, self.chain_id)
            
            return self._format_transaction_info(tx_data)
            
        except Exception as e:
            raise TransactionException(f"Failed to get transaction: {str(e)}", tx_hash, self.chain_id)
    
    async def get_transaction_receipt(self, tx_hash: str) -> Dict[str, Any]:
        """获取交易回执"""
        await self._ensure_connected()
        
        try:
            receipt = await self._call_java_method('getTransactionReceipt', {'txHash': tx_hash})
            
            if not receipt:
                raise TransactionException(f"Transaction receipt not found: {tx_hash}", tx_hash, self.chain_id)
            
            return receipt
            
        except Exception as e:
            raise TransactionException(f"Failed to get transaction receipt: {str(e)}", tx_hash, self.chain_id)
    
    async def estimate_gas(self, transaction: Dict[str, Any]) -> int:
        """估算Gas费用"""
        await self._ensure_connected()
        
        try:
            # JD Chain通常不使用Gas概念，返回默认值
            return 0
            
        except Exception as e:
            logger.warning(f"Gas estimation not supported in JD Chain: {str(e)}")
            return 0
    
    async def get_latest_block(self) -> BlockInfo:
        """获取最新区块"""
        await self._ensure_connected()
        
        try:
            # 使用HTTP网关API获取最新区块
            gateway_url = f"http{'s' if self.gateway_secure else ''}://{self.gateway_host}:{self.gateway_port}"
            
            import requests
            
            response = requests.get(f"{gateway_url}/ledgers/{self.ledger_hash}/blocks/latest")
            response.raise_for_status()
            
            result = response.json()
            if not result.get('success', False):
                raise ChainException(f"Failed to get latest block: {result.get('error', {}).get('errorMessage', 'Unknown error')}", self.chain_id, 'get_latest_block')
            
            block_data = result.get('data', {})
            if not block_data:
                raise ChainException("Failed to get latest block", self.chain_id, 'get_latest_block')
            
            return self._format_block_info(block_data)
            
        except Exception as e:
            raise ChainException(f"Failed to get latest block: {str(e)}", self.chain_id, 'get_latest_block')
    
    async def get_block_by_number(self, block_number: int) -> BlockInfo:
        """根据区块号获取区块"""
        await self._ensure_connected()
        
        try:
            # 使用HTTP网关API获取指定高度的区块
            gateway_url = f"http{'s' if self.gateway_secure else ''}://{self.gateway_host}:{self.gateway_port}"
            
            import requests
            
            response = requests.get(f"{gateway_url}/ledgers/{self.ledger_hash}/blocks/height/{block_number}")
            response.raise_for_status()
            
            result = response.json()
            if not result.get('success', False):
                raise ChainException(f"Failed to get block by number: {result.get('error', {}).get('errorMessage', 'Unknown error')}", self.chain_id, 'get_block_by_number')
            
            block_data = result.get('data', {})
            if not block_data:
                raise ChainException(f"Block not found: {block_number}", self.chain_id, 'get_block_by_number')
            
            return self._format_block_info(block_data)
            
        except Exception as e:
            raise ChainException(f"Failed to get block by number: {str(e)}", self.chain_id, 'get_block_by_number')
    
    async def get_block_by_hash(self, block_hash: str) -> BlockInfo:
        """根据区块哈希获取区块"""
        await self._ensure_connected()
        
        try:
            # 使用HTTP网关API获取指定哈希的区块
            gateway_url = f"http{'s' if self.gateway_secure else ''}://{self.gateway_host}:{self.gateway_port}"
            
            import requests
            
            response = requests.get(f"{gateway_url}/ledgers/{self.ledger_hash}/blocks/hash/{block_hash}")
            response.raise_for_status()
            
            result = response.json()
            if not result.get('success', False):
                raise ChainException(f"Failed to get block by hash: {result.get('error', {}).get('errorMessage', 'Unknown error')}", self.chain_id, 'get_block_by_hash')
            
            block_data = result.get('data', {})
            if not block_data:
                raise ChainException(f"Block not found: {block_hash}", self.chain_id, 'get_block_by_hash')
            
            return self._format_block_info(block_data)
            
        except Exception as e:
            raise ChainException(f"Failed to get block by hash: {str(e)}", self.chain_id, 'get_block_by_hash')
    
    async def get_block(self, block_identifier) -> BlockInfo:
        """根据区块号或区块哈希获取区块"""
        if isinstance(block_identifier, int):
            return await self.get_block_by_number(block_identifier)
        elif isinstance(block_identifier, str):
            return await self.get_block_by_hash(block_identifier)
        else:
            raise ChainException(f"Invalid block identifier type: {type(block_identifier)}", self.chain_id, 'get_block')
    
    async def deploy_contract(self, contract_data: Dict[str, Any]) -> ContractInfo:
        """部署智能合约"""
        await self._ensure_connected()
        
        try:
            # JD Chain合约部署
            deploy_data = {
                'contractName': contract_data.get('name'),
                'contractCode': contract_data.get('code'),
                'contractVersion': contract_data.get('version', '1.0.0'),
                'lang': contract_data.get('language', 'Java')
            }
            
            # 发送部署交易
            result = await self._call_java_method('deployContract', deploy_data)
            
            if not result or not result.get('contractAddress'):
                raise ContractException("Contract deployment failed", None, self.chain_id)
            
            contract_address = result.get('contractAddress')
            
            return ContractInfo(
                address=contract_address,
                name=contract_data.get('name', ''),
                abi=[],  # JD Chain不使用ABI概念
                bytecode=contract_data.get('code', ''),
                source_code=contract_data.get('source_code', ''),
                compiler_version=contract_data.get('compiler_version', ''),
                creation_transaction=result.get('txHash', ''),
                creator=contract_data.get('deployer', ''),
                creation_time=datetime.now()
            )
            
        except Exception as e:
            raise ContractException(f"Failed to deploy contract: {str(e)}", None, self.chain_id)
    
    async def call_contract(self, contract_address: str, method: str, 
                          params: Dict[str, Any] = None, **kwargs) -> Any:
        """调用智能合约方法"""
        await self._ensure_connected()
        
        try:
            # 处理参数格式 - 如果params是列表，转换为字典
            if isinstance(params, list):
                if method == 'set' and len(params) >= 2:
                    args = {'key': params[0], 'value': params[1]}
                elif method == 'get' and len(params) >= 1:
                    args = {'key': params[0]}
                else:
                    args = {}
            else:
                args = params or {}
            
            # 构建合约调用
            call_data = {
                'contractAddress': contract_address,
                'operation': method,
                'args': args
            }
            
            if kwargs.get('call_type') == 'call' or method == 'get':
                # 查询调用 - get操作总是查询操作
                result = await self._call_java_method('queryContract', call_data)
                # 对于get操作，_get_key_value直接返回值，不需要.get('result')
                if method == 'get':
                    return result
                else:
                    return result.get('result')
            else:
                # 交易调用
                call_data['txType'] = 'CONTRACT'
                return await self.send_transaction(call_data)
                
        except Exception as e:
            raise ContractException(f"Failed to call contract method: {str(e)}", contract_address, self.chain_id)
    
    async def get_contract_info(self, contract_address: str) -> ContractInfo:
        """获取智能合约信息"""
        await self._ensure_connected()
        
        try:
            # 查询合约信息
            contract_info = await self._call_java_method('getContractInfo', {
                'contractAddress': contract_address
            })
            
            return ContractInfo(
                address=contract_address,
                name=contract_info.get('name', '') if contract_info else '',
                abi=[],
                bytecode=contract_info.get('code', '') if contract_info else '',
                source_code='',
                compiler_version=contract_info.get('version', '') if contract_info else '',
                creation_transaction='',
                creator=contract_info.get('creator', '') if contract_info else '',
                creation_time=datetime.now()
            )
            
        except Exception as e:
            raise ContractException(f"Failed to get contract info: {str(e)}", contract_address, self.chain_id)
    
    async def subscribe_events(self, event_filter: Dict[str, Any], 
                             callback: callable) -> str:
        """订阅事件"""
        await self._ensure_connected()
        
        try:
            # JD Chain事件订阅实现
            subscription_id = f"sub_{len(self._subscriptions) + 1}"
            
            # 这里应该实现具体的事件订阅逻辑
            # JD Chain支持区块事件和交易事件订阅
            
            self._subscriptions[subscription_id] = {
                'filter': event_filter,
                'callback': callback,
                'active': True
            }
            
            logger.info(f"Event subscription created: {subscription_id}")
            return subscription_id
            
        except Exception as e:
            raise ChainException(f"Failed to subscribe events: {str(e)}", self.chain_id, 'subscribe_events')
    
    async def get_logs(self, filter_params: Dict[str, Any]) -> List[Dict[str, Any]]:
        """获取事件日志"""
        await self._ensure_connected()
        
        try:
            # JD Chain的事件查询
            log_filter = {
                'fromBlock': filter_params.get('from_block', 0),
                'toBlock': filter_params.get('to_block', -1),
                'contractAddress': filter_params.get('contract_address'),
                'eventType': filter_params.get('event_type')
            }
            
            logs = await self._call_java_method('getLogs', log_filter)
            return logs.get('logs', []) if logs else []
            
        except Exception as e:
            raise ChainException(f"Failed to get logs: {str(e)}", self.chain_id, 'get_logs')
    
    def _generate_request_id(self) -> str:
        """生成请求ID"""
        import uuid
        return str(uuid.uuid4()).replace('-', '')[:16]
    
    def _format_transaction_info(self, raw_tx: Dict[str, Any]) -> TransactionInfo:
        """格式化JD Chain交易信息"""
        return TransactionInfo(
            hash=raw_tx.get('txHash', ''),
            from_address=raw_tx.get('endpointSignature', {}).get('pubKey', ''),
            to_address=raw_tx.get('contractAddress', ''),
            value=0.0,  # JD Chain通常不涉及价值转移
            gas_limit=0,
            gas_price=0,
            nonce=0,
            data=json.dumps(raw_tx.get('operationResults', [])),
            block_number=raw_tx.get('blockHeight', 0),
            block_hash=raw_tx.get('blockHash', ''),
            transaction_index=raw_tx.get('txIndex', 0),
            status='success' if raw_tx.get('executionState') == 'SUCCESS' else 'failed',
            timestamp=datetime.fromtimestamp(raw_tx.get('timestamp', 0) / 1000)
        )
    
    def _format_block_info(self, raw_block: Dict[str, Any]) -> BlockInfo:
        """格式化JD Chain区块信息"""
        return BlockInfo(
            block_number=raw_block.get('height', 0),
            block_hash=raw_block.get('hash', ''),
            parent_hash=raw_block.get('previousHash', ''),
            timestamp=datetime.fromtimestamp(raw_block.get('timestamp', 0) / 1000),
            transactions=[tx.get('txHash', '') for tx in raw_block.get('txs', [])],
            gas_limit=0,
            gas_used=0,
            miner=raw_block.get('consensusProvider', '')
        )
    
    async def _call_java_method(self, method_name: str, params: Dict[str, Any] = None) -> Dict[str, Any]:
        """调用Java方法的通用接口，直接调用JDChain Spring Boot REST API
        
        由于JD Chain官方不支持Python SDK，此方法通过HTTP网关API实现
        将Java SDK的调用转换为HTTP API调用
        """
        try:
            if params is None:
                params = {}
            
            # 根据方法名映射到对应的HTTP API端点
            if method_name == 'createAccount':
                # 账户创建通过交易实现
                return await self._http_request('POST', '/accounts', params)
            elif method_name == 'getAccount':
                # 获取账户信息
                address = params.get('address', '')
                return await self._http_request('GET', f'/accounts/{address}')
            elif method_name == 'sendTransaction':
                # 发送交易 - 对于合约调用，直接使用set操作
                operation = params.get('operation', '')
                args = params.get('args', {})
                if operation == 'setKeyValue' and 'key' in args and 'value' in args:
                    return await self._set_key_value(args['key'], args['value'])
                elif operation == 'set' and 'key' in args and 'value' in args:
                    return await self._set_key_value(args['key'], args['value'])
                elif operation == 'get' and 'key' in args:
                    # get操作应该是查询操作，不是交易操作
                    return await self._get_key_value(args['key'])
                else:
                    # 其他类型的交易暂时不支持
                    raise ChainException(f"Unsupported transaction operation: {operation}")
            elif method_name == 'getTransaction':
                # 获取交易信息
                tx_hash = params.get('txHash', '')
                return await self._http_request('GET', f'/transactions/{tx_hash}')
            elif method_name == 'getTransactionReceipt':
                # 获取交易回执
                tx_hash = params.get('txHash', '')
                return await self._http_request('GET', f'/transactions/{tx_hash}/receipt')
            elif method_name == 'deployContract':
                # 部署合约
                return await self._http_request('POST', '/contracts/deploy', params)
            elif method_name == 'queryContract':
                # 查询合约
                contract_address = params.get('contractAddress', '')
                operation = params.get('operation', '')
                args = params.get('args', {})
                if operation == 'get' and 'key' in args:
                    # 直接调用get方法
                    return await self._get_key_value(args['key'])
                else:
                    # 其他查询操作暂时不支持
                    raise ChainException(f"Unsupported query operation: {operation}")
            elif method_name == 'getContractInfo':
                # 获取合约信息
                contract_address = params.get('contractAddress', '')
                return await self._http_request('GET', f'/contracts/{contract_address}')
            elif method_name == 'getLogs':
                # 获取事件日志
                return await self._http_request('POST', '/logs/query', params)
            elif method_name == 'setKeyValue':
                # 设置键值对数据
                key = params.get('key', '')
                value = params.get('value', '')
                return await self._set_key_value(key, value)
            elif method_name == 'getKeyValue':
                # 获取键值对数据
                key = params.get('key', '')
                return await self._get_key_value(key)
            else:
                # 未知方法，尝试通用调用
                logger.warning(f"Unknown Java method: {method_name}, attempting generic call")
                return await self._http_request('POST', f'/java/{method_name}', params)
                
        except Exception as e:
            logger.error(f"Failed to call Java method {method_name}: {str(e)}")
            raise ChainException(f"Java method call failed: {str(e)}")
    
    async def _set_key_value(self, key, value):
        """设置键值对数据"""
        try:
            url = f"{self.api_base_url}/set"
            data = {"key": key, "value": value}
            logger.info(f"Calling JDChain API: {url} with data: {data}")
            
            async with aiohttp.ClientSession() as session:
                async with session.post(url, json=data, headers={'Content-Type': 'application/json'}) as response:
                    logger.info(f"JDChain API response status: {response.status}")
                    response_text = await response.text()
                    logger.info(f"JDChain API response text: {response_text}")
                    
                    response.raise_for_status()
                    result = await response.json()
                    logger.info(f"JDChain API response JSON: {result}")
                    
                    if result.get('success'):
                        return {
                            'success': True,
                            'txHash': result.get('data'),  # 修改为txHash以匹配send_transaction的期望
                            'transaction_hash': result.get('data'),
                            'message': result.get('message', '设置成功')
                        }
                    else:
                        raise ChainException(f"Set key-value failed: {result.get('message', 'Unknown error')}")
                        
        except Exception as e:
            logger.error(f"Failed to set key-value: {str(e)}")
            raise ChainException(f"Failed to set key-value: {str(e)}")
    
    async def _get_key_value(self, key):
        """获取键值对数据"""
        try:
            url = f"{self.api_base_url}/get/{key}"
            logger.info(f"Calling JDChain API: {url}")
            
            async with aiohttp.ClientSession() as session:
                async with session.get(url) as response:
                    logger.info(f"JDChain API response status: {response.status}")
                    response_text = await response.text()
                    logger.info(f"JDChain API response text: {response_text}")
                    
                    response.raise_for_status()
                    result = await response.json()
                    logger.info(f"JDChain API response JSON: {result}")
                    
                    if result.get('success'):
                        logger.info(f"Successfully retrieved value for key '{key}': {result.get('data')}")
                        return {
                            'success': True,
                            'value': result.get('data'),
                            'message': result.get('message', '获取成功')
                        }
                    else:
                        raise ChainException(f"Get key-value failed: {result.get('message', 'Unknown error')}")
                        
        except Exception as e:
             logger.error(f"Failed to get key-value: {str(e)}")
             raise ChainException(f"Failed to get key-value: {str(e)}")
    
    async def set(self, key: str, value: str) -> Dict[str, Any]:
        """设置键值对数据"""
        try:
            if not await self.is_connected():
                raise ChainException("Not connected to JD Chain")
            
            # 直接调用JDChain Spring Boot REST API
            result = await self._set_key_value(key, value)
            
            return {
                'success': True,
                'transaction_hash': result.get('transaction_hash'),
                'message': result.get('message', 'Data set successfully')
            }
            
        except Exception as e:
            logger.error(f"Failed to set data: {str(e)}")
            raise ChainException(f"Failed to set data: {str(e)}")
    
    async def get(self, key: str) -> Dict[str, Any]:
        """获取键值对数据"""
        try:
            if not await self.is_connected():
                raise ChainException("Not connected to JD Chain")
            
            # 直接调用JDChain Spring Boot REST API
            result = await self._get_key_value(key)
            
            return {
                'success': True,
                'value': result.get('value'),
                'message': result.get('message', 'Data retrieved successfully')
            }
            
        except Exception as e:
            logger.error(f"Failed to get data: {str(e)}")
            raise ChainException(f"Failed to get data: {str(e)}")